//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------

#ifndef _UXS_CONTAINER_MEM_MOVER_H
#define _UXS_CONTAINER_MEM_MOVER_H

#pragma once

#include "TArray.h"
#include "TString.h"
#include "TQueue.h"
#include "TSet.h"
#include "TMap.h"

namespace UX_STL
{
namespace UXTypes
{

	//
	// Containers Memory Mover
	//

	struct MemMover
	{
		template <typename T, typename S, typename A, typename T2, typename S2, typename A2>
		static void Swap (TString<T,S,A> &left, array<T2,S2,A2> &right);
		
		template <typename T, typename S, typename A, typename T2, typename S2, typename A2>
		static void Swap (array<T,S,A> &left, array<T2,S2,A2> &right);
		
		template <typename T, typename S, typename A, typename T2, typename S2, typename A2>
		static void Swap (set<T,S,A> &left, array<T2,S2,A2> &right);

		template <typename K, typename T, typename S, typename A,
				  typename K2, typename T2, typename S2, typename A2>
		static void Swap (map<K,T,S,A> &left, map<K2,T2,S2,A2> &right);
	};

	
	

	template <typename T, typename S, typename A,
			  typename T2, typename S2, typename A2
			 >
	inline void MemMover::Swap (array<T,S,A> &left, array<T2,S2,A2> &right)
	{
		// TODO: check allocators

		usize		temp;

		_swap( (void *&)left._pMemory,	(void *&)right._pMemory,	(void *&)temp );
		_swap( left._uCount,			right._uCount,				temp );
		_swap( left._uSize,				right._uSize,				temp );

		left._uCount	= ( left._uCount * sizeof(T2) ) / sizeof(T);
		left._uSize		= ( left._uSize  * sizeof(T2) ) / sizeof(T);

		right._uCount	= ( right._uCount * sizeof(T) ) / sizeof(T2);
		right._uSize	= ( right._uSize  * sizeof(T) ) / sizeof(T2);
	}


	template <typename T, typename S, typename A,
			  typename T2, typename S2, typename A2
			 >
	inline void MemMover::Swap (TString<T,S,A> &left, array<T2,S2,A2> &right)
	{
		// TODO: check allocators

		usize		temp;

		_swap( (void *&)left._pMemory,	(void *&) right._pMemory,	(void *&)temp );
		_swap( left._uCount,			right._uCount,				temp );
		_swap( left._uSize,				right._uSize,				temp );


		if ( left._IsEmpty( (T *)right._pMemory ) )
		{
			right._pMemory	= null;
			right._uCount	= 0;
			right._uSize	= 0;
		}
		else
		{
			right._uCount	= ( right._uCount * sizeof(T) ) / sizeof(T2);
			right._uSize	= ( right._uSize  * sizeof(T) ) / sizeof(T2);
		}

		if ( left._pMemory == null )
		{
			left._pMemory	= (T*) left._s_aEmpty;
			left._uCount	= 1;
			left._uSize		= 1;
		}
		else
		{
			left._uCount	= ( left._uCount * sizeof(T2) ) / sizeof(T);
			left._uSize		= ( left._uSize  * sizeof(T2) ) / sizeof(T);
		}
	}
	
	
	template <typename K, typename T, typename S, typename A,
			  typename K2, typename T2, typename S2, typename A2
			 >
	inline void MemMover::Swap (map<K,T,S,A> &left, map<K2,T2,S2,A2> &right)
	{
		STATIC_ASSERTE( sizeof(K) == sizeof(K2) );

		Swap( left._aNodes, right._aNodes );
	}
	
	template <typename T, typename S, typename A,
			  typename T2, typename S2, typename A2
			 >
	inline void MemMover::Swap (set<T,S,A> &left, array<T2,S2,A2> &right)
	{
		STATIC_ASSERTE( sizeof(T) == sizeof(T2) );

		Swap( left._aNodes, right );
	}

//-------------------------------------------------------------------

}	// UXTypes
}	// UX_STL

#endif	// _UXS_CONTAINER_MEM_MOVER_H